home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: MegaDisc
/
MegaDisc 28 (1992-05)(MegaDisc Digital Publishing)(AU)(Disk 2 of 2).zip
/
MegaDisc 28 (1992-05)(MegaDisc Digital Publishing)(AU)(Disk 2 of 2).adf
/
Programming
/
ILBM_Prog
/
ILBM_Code
/
ILBM.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-26
|
16KB
|
470 lines
/************************************************************************
ILBM.c
Routines for reading IFF_ILBM files.
28/02/1992 by Ray Markham.
This code is included with the article for using IFF_ILBM files in
MEGADISC 27.
This code is in the public domain. So you can use it and abuse it to
your heart's content.
The code also follows the EA standards for file access.
This file with ILBM.h compile to ILBM.o for linking with other code.
If you have any questions or you use this code in your own programs
please send me an example of the executable so I can see how well
the code is being used. I can be contacted at the following address:-
Ray Markham
P.O. Box 1590
Port Macquarie, NSW
2444
Australia
************************************************************************/
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include "ILBM.h"
extern struct FileHandle *Open();
extern PLANEPTR AllocRaster();
/* ILBM.c functions. */
VOID ReadCMAP(); /* Read the colour map into store */
VOID ReadABIT(); /* Read an ABIT chunk of ACBM file */
VOID ReadBitMAPheader(); /* Self explanitory. */
VOID ReadBODY(); /* To read the BODY chunk. */
VOID DecodeCompr(); /* deal with ByteRun1 compression */
VOID PlainRead(); /* body with no compression */
VOID ReadChunk(); /* Speaks for itself. Then decide what else */
VOID DumpChunk(); /* Not a useful ILBM/ACBM chunk. */
VOID FadeDown(); /* Fade up viewport from black to CMAP1 */
VOID FadeUp(); /* Fade viewport from CMAP1 to black. */
VOID BlackoutVP(); /* make CMAP2 black and load into viewport */
VOID PutCMAP(); /* put CMAP1 into viewport. */
BOOL ReadFile(); /* Do the file work. */
BOOL MakeBitMap();
BOOL FreeBitMap();
BOOL ReadChunkHeader();
struct FormHeader formheader; /* this is for the form header */
struct ChunkHeader chunkheader; /* chunk headers go here */
struct BitMapHeader bmHeader; /* storage for bit map header */
LONG bytesread; /* bytes read from file */
LONG totalbytes; /* total bytes on file */
LONG rLen; /* bytes read from disc */
USHORT cmap1[96]; /* colourmap */
USHORT cmap2[96]; /* spare colourmap for fade up/down */
UBYTE powers_of_two[] = { 2, 4, 8, 16, 32 };
/********************************************************************/
/* Here is the ILBM workhorse. The routine to open and start read. */
/********************************************************************/
BOOL ReadFile(filename,bitmap,viewport,code)
char *filename; /* filename */
struct BitMap *bitmap; /* bitmap to be used */
struct ViewPort *viewport; /* viewport address */
UBYTE code; /* colour change flag */
{
struct FileHandle *fHandle;
BOOL success = FALSE; /* successful open IFF_ILBM */
fHandle = Open(filename, MODE_OLDFILE); /* Open the file */
if(fHandle)
{
success = ReadChunkHeader(fHandle); /* Check for ILBM or ACBM */
if(success);
{
while (bytesread<totalbytes)
ReadChunk(fHandle,bitmap,viewport,code);
}
Close(fHandle); /* See this one closes what it uses */
}
return(success);
}
/************************************************************/
/* Read the ChunkhHader. Store the length */
/* and check for an ILBM or ACBM file */
/************************************************************/
BOOL ReadChunkHeader(fHandle)
struct FileHandle *fHandle;
{
BOOL success;
rLen = Read(fHandle,&formheader,sizeof(struct FormHeader));
/* read the header block */
bytesread = rLen;
totalbytes = formheader.Size; /* file is this big */
switch(formheader.Type)
{
case ID_ILBM:
success = TRUE; /* if ILBM */
break;
case ID_ACBM:
success = TRUE; /* if ACBM */
break;
default:
success = FALSE; /* File is not for us. */
break;
}
return (success);
}
/************************************************************************/
/* Routine for reading a ChunkHeader and deciding what to call to read */
/************************************************************************/
VOID ReadChunk(fHandle,bitmap,viewport,code)
struct FileHandle *fHandle;
struct BitMap *bitmap;
struct ViewPort *viewport;
UBYTE code;
{
rLen = Read(fHandle,&chunkheader,sizeof(struct ChunkHeader));
bytesread += sizeof (struct ChunkHeader);
bytesread += chunkheader.Size;
switch(chunkheader.Header)
{
case ID_BMHD:
ReadBitMAPheader(fHandle,bitmap,code);
break;
case ID_CMAP:
ReadCMAP(fHandle,viewport,code);
break;
case ID_BODY:
ReadBODY(fHandle,bitmap);
break;
case ID_ABIT:
ReadBODY(fHandle,bitmap);
break;
default: /* Not a chunk that we want */
DumpChunk(fHandle); /* so get rid of it... */
break;
}
}
/************************************************************************/
/* Routine for reading the Bit Map Header chunk and decoding it. */
/************************************************************************/
VOID ReadBitMAPheader(fHandle,bitmap,code)
struct FileHandle *fHandle;
struct BitMap *bitmap;
UBYTE code;
{
/* just read the bit map header into our BitMapHeader structure */
/* and we'll just access it directly from here. */
rLen = Read(fHandle,&bmHeader,sizeof(struct BitMapHeader));
}
/************************************************************************/
/* this chunk contains the colour information */
/************************************************************************/
VOID ReadCMAP(fHandle,viewport,code)
struct FileHandle *fHandle;
struct ViewPort *viewport;
UBYTE code;
{
LONG count;
char *tempbuffer;
if(chunkheader.Size & 1) { chunkheader.Size++; }
tempbuffer=(char *)AllocMem(chunkheader.Size, MEMF_PUBLIC);
rLen = Read(fHandle,tempbuffer,chunkheader.Size);
switch(code)
{
case NO_USE_CMAP: /* leave our existing CMAP resident */
break;
case OK_USE_CMAP: /* load the pictures CMAP and use it */
for (count = 0; count < chunkheader.Size; count++)
{
cmap1[count] = ( tempbuffer[count] & 0xff ) >> 4;
cmap2[count] = 0;
}
break;
default:
break;
}
FreeMem(tempbuffer,chunkheader.Size); /* free buffer */
}
/************************************************************************/
/* the abit chunk of an acbm file can be read straight onto the raster */
/************************************************************************/
VOID ReadABIT(fHandle,bitmap)
struct FileHandle *fHandle;
struct BitMap *bitmap;
{
USHORT i;
SHORT iHeight;
iHeight = bmHeader.pageHeight;
for (i=0; i < bmHeader.nPlanes; i++)
rLen = Read(fHandle,bitmap->Planes[i],((bmHeader.width)/8)*bmHeader.pageHeight);
}
/************************************************************************/
/* the body chunk of an ilbm file */
/************************************************************************/
VOID ReadBODY(fHandle,bitmap)
struct FileHandle *fHandle;
struct BitMap *bitmap;
{
char *tempbuffer;
tempbuffer=(char *)AllocMem(chunkheader.Size, MEMF_PUBLIC);
/* allocate temp buffer */
rLen = Read(fHandle,tempbuffer,chunkheader.Size);
/* read data */
switch(bmHeader.compression) /* decompress if required */
{
case cmpNone:
PlainRead(tempbuffer, bitmap); /* no compression */
break;
case cmpByteRun1:
DecodeCompr(tempbuffer, bitmap); /* normal compression */
break;
default:
printf("Unknown Compression Algorithm \n");
break;
}
FreeMem(tempbuffer,chunkheader.Size); /* free buffer */
}
/************************************************************************/
/* don't want to use this chunk so I'll just dump it. */
/************************************************************************/
VOID DumpChunk(fHandle)
struct FileHandle *fHandle;
{
char *tempbuffer; /* pointer to temporary storage */
tempbuffer = (char *)AllocMem(chunkheader.Size, MEMF_PUBLIC);
/* alloc work buffer */
rLen = Read(fHandle,tempbuffer,chunkheader.Size);
/* read the chunk into store */
FreeMem(tempbuffer,chunkheader.Size); /* free buffer */
}
/************************************************************************/
/* decode a compressed file */
/* read the next byte inCode */
/* if inCode<128 read the next inCode+1 bytes normally */
/* if inCode>128 the next inCode+1 bytes are the same as the next one */
/************************************************************************/
VOID DecodeCompr(tempbuffer, bitmap)
char *tempbuffer;
struct BitMap *bitmap;
{
USHORT rows,planes,columns;
UBYTE bCnt,inCode,inByte;
UBYTE *place;
UBYTE *scrRow;
SHORT iHeight;
place = (UBYTE *)tempbuffer;
iHeight = bmHeader.pageHeight;
for (rows=0;rows<iHeight;rows++)
{
for (planes=0;planes<bmHeader.nPlanes;planes++)
{
scrRow=bitmap->Planes[planes] + (rows*(bmHeader.width)/8);
bCnt=0;
while(bCnt<(bmHeader.pageWidth)/8)
{
inCode=*(place);
place++;
if (inCode<128)
{
for(columns=0;columns<inCode+1;columns++)
*(scrRow+bCnt+columns)=*(place++);
bCnt=bCnt+inCode+1;
}
else if (inCode>128)
{
inByte= *(place);
for(columns=0;columns<257-inCode;columns++)
*(scrRow+bCnt+columns)=inByte;
bCnt=bCnt+257-inCode;
place++;
}
}
}
}
}
/************************************************************************/
/* no compression, but the bitplanes are interleaved */
/************************************************************************/
VOID PlainRead(tempbuffer, bitmap)
char *tempbuffer;
struct BitMap *bitmap;
{
SHORT rows,planes;
SHORT iHeight;
LONG columns;
char *scrRow;
char *pointer = tempbuffer;
iHeight = bmHeader.pageHeight;
for (rows=0; rows < iHeight; rows++)
{
for (planes=0; planes < bmHeader.nPlanes; planes++)
{
scrRow=bitmap->Planes[planes] + rows * (bmHeader.width)/8;
for (columns=0; columns < (bmHeader.pageWidth)/8; columns++)
{
*(scrRow+columns)=*(pointer++);
}
}
}
}
/********************************************************************/
/* Routines for allocating and deallocating BitMap storage */
/********************************************************************/
BOOL MakeBitMap(bitmap, depth, width, height)
struct BitMap *bitmap;
USHORT depth, width, height;
{
USHORT loop;
BOOL success = TRUE;
InitBitMap(bitmap, depth, width, height);
for(loop = 0; loop<depth; loop++)
{
bitmap->Planes[loop] = AllocRaster( width, height );
if(bitmap->Planes == 0)
{
success = FALSE;
}
}
return(success);
}
BOOL FreeBitMap(bitmap)
struct BitMap *bitmap;
{
USHORT i, depth, bytes, rows;
depth = (bitmap->Depth)&255;
bytes = (bitmap->BytesPerRow)&0xffff;
rows = (bitmap->Rows)&0xffff;
for (i=0;i<depth;i++)
{
FreeRaster(bitmap->Planes[i],8*bytes,rows);
}
return(0);
}
/************************************************************************/
/* these two routines have nothing to do with reading the file but it */
/* made things easier to have them in the same module as the colourmap */
/************************************************************************/
VOID FadeDown(viewport) /*slowly decrease each colour intensity*/
struct ViewPort *viewport;
{
USHORT colour_cnt;
USHORT cmap_ptr;
USHORT nColours;
USHORT passes; /* maximum colour setting is 15 */
nColours = powers_of_two[bmHeader.nPlanes];
for(passes = 0; passes<15; passes++)
{
for(colour_cnt = 0, cmap_ptr = 0; colour_cnt <= nColours; colour_cnt++, cmap_ptr+=3)
{
if (cmap2[cmap_ptr]) cmap2[cmap_ptr]--;
if (cmap2[cmap_ptr+1]) cmap2[cmap_ptr+1]--;
if (cmap2[cmap_ptr+2]) cmap2[cmap_ptr+2]--;
SetRGB4(viewport, colour_cnt,
cmap2[cmap_ptr], cmap2[cmap_ptr+1], cmap2[cmap_ptr+2]);
}
Delay(2);
}
}
VOID FadeUp(viewport) /*slowly increase each colour intensity*/
struct ViewPort *viewport;
{
USHORT colour_cnt;
USHORT cmap_ptr;
USHORT nColours;
USHORT passes; /* maximum colour setting is 15 */
nColours = powers_of_two[bmHeader.nPlanes];
for(passes = 0; passes<15; passes++)
{
for(colour_cnt = 0, cmap_ptr = 0; colour_cnt <= nColours; colour_cnt++, cmap_ptr+=3)
{
if (cmap2[cmap_ptr] < cmap1[cmap_ptr]) cmap2[cmap_ptr]++;
if (cmap2[cmap_ptr+1] < cmap1[cmap_ptr+1]) cmap2[cmap_ptr+1]++;
if (cmap2[cmap_ptr+2] < cmap1[cmap_ptr+2]) cmap2[cmap_ptr+2]++;
SetRGB4(viewport, colour_cnt,
cmap2[cmap_ptr], cmap2[cmap_ptr+1], cmap2[cmap_ptr+2]);
}
Delay(2);
}
}
/************************************************************************/
/* make CMAP2 = black and load to viewport. */
/************************************************************************/
VOID BlackoutVP(viewport)
struct ViewPort *viewport;
{
USHORT count;
for(count = 0; count <= 96; count++) /* make CMAP2 = black */
{
cmap2[count] = 0;
}
LoadRGB4(viewport, cmap2, powers_of_two[bmHeader.nPlanes]);
}
/************************************************************************/
/* move CMAP1 into viewport. */
/************************************************************************/
VOID PutCMAP(viewport)
struct ViewPort *viewport;
{
LoadRGB4(viewport, cmap1, powers_of_two[bmHeader.nPlanes]);
}